﻿namespace ScrumFactory.Data.Sql
{
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.Linq;

    [Export(typeof(IProjectRepository))]
    public class SqlProjectRepository : IProjectRepository
    {
        private string connectionString;

        [ImportingConstructor()]
        public SqlProjectRepository(
            [Import("ScrumFactoryEntitiesConnectionString")]
            string connectionString)
        {
            this.connectionString = connectionString;
        }


        public ICollection<ScrumFactory.Project> GetRunningProjects() {
            using (var context = new ScrumFactoryEntities(this.connectionString)) {
                // EntityFramework does not recognize the extension method directly
                // that is why we call .ToList() to retrieve the whole resultset
                // and then we translate each entitiy
                return context.Projects.Where(p => p.Status == (short) ScrumFactory.ProjectStatus.PROJECT_STARTED).ToList();
                
            }
        }

        public ICollection<ScrumFactory.Project> GetAllProjects()
        {
            using (var context = new ScrumFactoryEntities(this.connectionString))
            {
                // EntityFramework does not recognize the extension method directly
                // that is why we call .ToList() to retrieve the whole resultset
                // and then we translate each entitiy
                return context.Projects.ToList();
            }
        }

        public ScrumFactory.Project GetProject(string projectUId)
        {
            using (var context = new ScrumFactoryEntities(this.connectionString))
            {
                return context.Projects.Include("Roles").Include("Sprints").SingleOrDefault(p => p.ProjectUId == projectUId);
                //return context.Projects.SingleOrDefault(p => p.ProjectUId == projectUId);
            }
        }

        public void InsertProject(ScrumFactory.Project project)
        {
            using (var context = new ScrumFactoryEntities(this.connectionString))
            {
                context.Projects.AddObject(project);
                context.SaveChanges();
            }
        }

        public void UpdateProject(ScrumFactory.Project project)
        {
            using (var context = new ScrumFactoryEntities(this.connectionString))
            {
                var projectEntity = context.Projects.SingleOrDefault(p => p.ProjectUId == project.ProjectUId);
                context.ApplyCurrentValues<Project>("Projects", project);

                context.SaveChanges();
            }
        }

        public ICollection<ScrumFactory.Role> GetProjectRoles(string projectUId) {
            using (var context = new ScrumFactoryEntities(this.connectionString)) {
                return context.Roles.Where(r => r.ProjectUId == projectUId).ToList();
            }
        }

        public Role GetProjectRole(string roleUId) {
            using (var context = new ScrumFactoryEntities(this.connectionString)) {
                return context.Roles.SingleOrDefault(r => r.RoleUId == roleUId);
            }
        }

        public void SaveProjectRole(ScrumFactory.Role role) {
            using (var context = new ScrumFactoryEntities(this.connectionString)) {
                Role oldRole = GetProjectRole(role.RoleUId);
                if (oldRole == null) {
                    context.Roles.AddObject(role);
                } else {
                    context.AttachTo("Roles", oldRole);
                    context.ApplyCurrentValues<Role>("Roles", role);
                }
                context.SaveChanges();
            }
        }

        public bool CanDeleteProjectRole(string roleUId) {
            using (var context = new ScrumFactoryEntities(this.connectionString)) {
                decimal? plannedHoursForThisRole = context.PlannedHours.Where(h => h.RoleUId == roleUId).Sum(h => h.Hours);
                if (plannedHoursForThisRole == null || plannedHoursForThisRole == 0)
                    return true;
            }
            return false;
        }

        public void DeleteProjectRole(string roleUId) {
            using (var context = new ScrumFactoryEntities(this.connectionString)) {
                Role oldRole = GetProjectRole(roleUId);
                context.AttachTo("Roles", oldRole);
                context.DeleteObject(oldRole);                
                context.SaveChanges();                           

                
            }
        }

        public ICollection<Sprint> GetSprints(string projectId) {
            using (var context = new ScrumFactoryEntities(this.connectionString)) {
                return context.Sprints.Where(s => s.ProjectUId == projectId).ToList();
            }
        }

        public Sprint GetSprint(string sprintUId) {
            using (var context = new ScrumFactoryEntities(this.connectionString)) {
                return context.Sprints.Where(s => s.SprintUId == sprintUId).SingleOrDefault();
            }
        }

        public void SaveSprint(Sprint sprint) {
            using (var context = new ScrumFactoryEntities(this.connectionString)) {

                Sprint oldSprint = GetSprint(sprint.SprintUId);

                // if is a new item insert it
                if (oldSprint == null) {
                    context.Sprints.AddObject(sprint);

                    // updates the item
                } else {
                    context.AttachTo("Sprints", oldSprint);
                    context.ApplyCurrentValues<Sprint>("Sprints", sprint);
                }

                context.SaveChanges();

            }
        }

       
    }
}
